/*
 * Audiogram.fx
 *
 * Created on Mar 2, 2009, 2:50:58 PM
 */

package hlequaliser;

import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Line;
import javafx.scene.paint.Color;
import javafx.scene.input.MouseEvent;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextOrigin;
import javafx.scene.paint.Color;

/**
 * @author forsakendaemon
 */

public class Audiogram extends CustomNode {

    public-init var width: Integer = 200;
    public-init var height: Integer = 200;
    public-init var x: Integer = 0;
    public-init var y: Integer = 0;

    public-read var leftValues: Number[] = [0,0,-20,0,-20,0,-20,0,-20,0];
    public-read var rightValues: Number[] = [0,0,-20,0,-20,0,-20,0,-20,0];
    public-read var rightMaskedValues: Number[] = [-20,-20,-20,-20,-20,-20,-20,-20];
    public-read var leftMaskedValues: Number[] = [-20,-20,-20,-20,-20,-20,-20,-20];

    

    def freqs: Number[] = [250, 500, 750, 1000, 1500, 2000, 3000, 4000, 6000, 8000];
    def values: Number[] = [-10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
    def xStep: Integer = bind (sizeof values - 1);
    def yStep = bind (sizeof freqs + 1);

    var rightSelected: Boolean = true;
    var maskedSelected: Boolean = false;

    var rightMarks: Right[] = bind for (right in rightValues)
        Right {
            x: ((indexof right + 1) * width / yStep + x),
            y: ((right + 10) * 0.1 * height / xStep + y),
            visible: if (right == -20) then false else true,
        };
    var leftMarks: Left[] = bind for (left in leftValues)
        Left {
            x: ((indexof left + 1) * width / yStep + x),
            y: ((left + 10) * 0.1 * height / xStep + y),
            visible: if (left == -20) then false else true,
        };
    var rightMaskedMarks: Right[] = bind for (right in rightMaskedValues)
        Right {
            x: ((indexof right + 1) * width / yStep + x),
            y: ((right + 10) * 0.1 * height / xStep + y),
            visible: if (right == -20) then false else true,
            masked: true,
        };
    var leftMaskedMarks: Left[] = bind for (left in leftMaskedValues)
        Left {
            x: ((indexof left + 1) * width / yStep + x),
            y: ((left + 10) * 0.1 * height / xStep + y),
            visible: if (left == -20) then false else true,
            masked: true,
        };
    def selectionRectangle: Rectangle = Rectangle {
        width: 50,
        height: 50,
        x: bind (x + width + 40 + (if (maskedSelected) then 50 else 0)),
        y: bind (y + height / 2 - 50 + (if (not rightSelected) then 50 else 0)),
        fill: Color.GREY;
    }

    def s: Group = Group {
        content: [
            Rectangle {
                x: x;
                y: y;
                width: width,
                height: height,
                fill: Color.WHITE,
                stroke: Color.BLACK
                onMouseClicked: function(event: MouseEvent):Void {
                    //println("{event.node.getClass().toString()} x:{event.x} y:{event.y} sceneX:{event.sceneX} sceneY: {event.sceneY}");
                    //TODO This doesn't behave the way that it should. Maybe ask someone?
                    var xOffset = (
                    (event.x - x) * yStep / width - 0.5) as Integer;
                    var yOffset = (
                    (event.y - y) * xStep / height - 0.5) as Integer;
                    yOffset = yOffset * 10;
                    var temp = if (rightSelected) then
                        if (maskedSelected) then rightMaskedValues else rightValues
                    else
                        if (maskedSelected) then leftMaskedValues else leftValues;
                    if (temp[xOffset] == yOffset) {
                        temp[xOffset] = -20;
                    } else {
                        temp[xOffset] = yOffset;
                    };
                    if (rightSelected) {
                        if (maskedSelected) {
                            rightMaskedValues = temp;
                        } else {
                            rightValues = temp;
                        }
                    } else {
                        if (maskedSelected) {
                            leftMaskedValues = temp;
                        } else {
                            leftValues = temp;
                        }
                    }
                }
            },
            for (value in values) {
                    Group {
                        content: [
                            Line {
                                startX: x,
                                endX: width + x,
                                startY: ((indexof value) * height / xStep + y),
                                endY: ((indexof value) * height / xStep + y),
                            },
                            Text {
                                x: x - 25,
                                y: (indexof value) * height / xStep + y,
                                content: "{value as Integer}";
                                textAlignment: TextAlignment.RIGHT;
                                textOrigin: TextOrigin.BASELINE; //TODO Change this to be middle-aligned. Requires addition to JavaFX SDK.
                            }
                        ]
                    }

                },
            for (freq in freqs) {
                Group {
                    content: [
                        Line {
                            startX: ((indexof freq + 1) * width / yStep + x),
                            endX: ((indexof freq + 1) * width / yStep + x),
                            startY: y,
                            endY:
                            height + y,
                            strokeDashArray: (if (((indexof freq + 1) mod 2 == 1) and not ((indexof freq) == 0)) then [2.0, 4.0] else [1.0]),
                        },
                        Text {
                            x: ((indexof freq) * width / yStep + x + 10),
                            y: y - 25,
                            textAlignment: TextAlignment.LEFT,
                            textOrigin: TextOrigin.TOP,
                            content: "{freq as Integer}",
                            rotate: -45,
                        }
                    ]
                }
            },
            Rectangle {
                x: x + width + 40,
                y: y + height / 2 - 50,
                width: 100,
                height: 100,
                fill: Color.WHITE,
                stroke: Color.BLACK,
                onMouseClicked: function(event:MouseEvent) {
                    rightSelected = (if (event.y < y + height / 2) then true else false);
                    maskedSelected = (if (event.x > x + width + 90) then true else false);
                }
            },
            selectionRectangle,

            Right {
                x: x + width + 65,
                y: y + height / 2 - 25,
            },
            Left {
                x: x + width + 65,
                y: y + height / 2 + 25,
            },
            Right {
                x: x + width + 115,
                y: y + height / 2 - 25,
                masked: true,
            },
            Left {
                x: x + width + 115,
                y: y + height / 2 + 25,
                masked: true,
            },

            Group {
                content: bind [
                    rightMarks,
                    leftMarks,
                    rightMaskedMarks,
                    leftMaskedMarks,
                ]
            },
            Text {
                x: x + width / 2,
                y: y - 50,
                content: "Frequency (dB)",
                textAlignment: TextAlignment.CENTER,
            }
        ]
    };

    public override function create(): Node {
        return Group {
            content: [s]
        };
    }
}
